package org.mathcloud.math.core.scilab.manager;

import java.io.File;
import java.io.FileNotFoundException;

import org.mathcloud.math.core.common.signature.ObjectSignature;
import org.mathcloud.math.core.scilab.factory.ScilabQuantityObjectFactory;
import org.mathcloud.math.core.scilab.quantity.ScilabQuantityObject;
import org.scilab.modules.javasci.JavasciException;
import org.scilab.modules.javasci.JavasciException.InitializationException;
import org.scilab.modules.javasci.Scilab;
import org.scilab.modules.types.ScilabDouble;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ScilabSupervisor
{	
	public static synchronized Scilab getScilabEngine()
	{
		if (sciEngine!=null)
			return sciEngine;
		else
		{
			try
			{
				sciEngine = new Scilab();
				try
				{
					sciEngine.open();
					return sciEngine;
				} catch (JavasciException e)
				{
					log.error(e.toString());
					return null;
				}

			} catch (InitializationException e)
			{
				log.error(e.toString());
				return null;
			}			
		}
	}
	public static long getVarId()
	{
		sciVarId ++;
		return sciVarId;
	}
	
	public static boolean run(String sciJob, Logger log)
	{
		boolean res = false;
		res = getScilabEngine().exec(sciJob);
		if (log!=null)
		{
			log.info(sciJob);
			if (!res)
				log.info(getScilabEngine().getLastErrorMessage());
		}	
		return res;
	}
	
	public static boolean run(File source, Logger log)
	{
		boolean res = false;
		try
		{
			res = getScilabEngine().exec(source);
			if (log!=null)
			{
				if (!res)
					log.info(getScilabEngine().getLastErrorMessage());
			}				
		} catch (FileNotFoundException e)
		{
			log.error("Source is not valid", e);
		}
		return res;		
	}
	
	public static String getScilabName(ObjectSignature sign)
	{
		return "scilab_"+sign.getObjectType()+"_"+ScilabSupervisor.getVarId();
	}
	
	public static int getScilabType(String var, Logger log) //analog to scilab function "type" 
	{
		String tmpVar0 = "tmp_"+getVarId();
		String sciJob = tmpVar0 + "=type("+var+");";
		if (run(sciJob,log))
		{
			try
			{
				ScilabDouble tmpVar1;
				tmpVar1 = (ScilabDouble) getScilabEngine().get(tmpVar0);
				int res = (int) tmpVar1.getRealPart()[0][0];
				sciJob = "clear " + tmpVar0+";";
				run(sciJob,log);
				return res;
			} catch (JavasciException e)
			{
				log.error(e.getMessage());
				return -1;
			}
		}
		else return -1;
	}
	
	public static ScilabQuantityObject evaluate(String code, Logger log) 
	{
		String tmpVar = "tmp_"+getVarId();
		String sciJob = tmpVar+"="+code+";";
		ScilabQuantityObject res = null;
		if (run(sciJob, log))
		{
    	try
			{
    		ScilabDouble tRes = (ScilabDouble)sciEngine.get(tmpVar);
      	res = ScilabQuantityObjectFactory.getInstance(tRes);
				sciJob = "clear "+tmpVar+";";
				run(sciJob,log);
			} catch (JavasciException e)
			{
				log.error("Cannot get value from Scilab",e);
			}			
		}
		return res;
	}
	
	public static Scilab sciEngine = null;
	public static long sciVarId = 0;
	private static final Logger log = LoggerFactory.getLogger(ScilabSupervisor.class);
}
